package com.saianfu.flowable.demo.common.impl

import com.saianfu.flowable.demo.common.ActTaskQuery
import com.saianfu.flowable.demo.common.VariablesEnum
import org.flowable.engine.HistoryService
import org.flowable.engine.RuntimeService
import org.flowable.engine.TaskService
import org.flowable.task.api.Task
import org.flowable.task.api.TaskQuery
import org.flowable.task.api.history.HistoricTaskInstance
import org.flowable.task.api.history.HistoricTaskInstanceQuery
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

/**
 * 流程任务查询
 *
 */
@Component
class TaskQueryHandler : ActTaskQuery {

    @Autowired
    lateinit var taskService: TaskService

    @Autowired
    lateinit var historyService: HistoryService

    @Autowired
    lateinit var runtimeService: RuntimeService

    override fun createTaskQuery(): TaskQuery {
        return taskService.createTaskQuery()
    }

    override fun createHistoricTaskInstanceQuery(): HistoricTaskInstanceQuery? {
        return historyService.createHistoricTaskInstanceQuery()
    }

    override fun taskId(taskId: String): Task? {
        return createTaskQuery()!!.taskId(taskId).singleResult()
    }

    override fun taskCandidateUser(candidateUser: String, start: Int, limit: Int): List<Task> {
        return createTaskQuery()!!.taskCandidateUser(candidateUser)
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun taskAssignee(assignee: String, start: Int, limit: Int): List<Task> {
        return createTaskQuery()!!.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun taskCandidateOrAssigned(userId: String, start: Int, limit: Int): List<Task> {
        return createTaskQuery()!!.taskCandidateOrAssigned(userId).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun taskAssigneeHistory(assignee: String, start: Int, limit: Int): List<HistoricTaskInstance> {
        return createHistoricTaskInstanceQuery()!!.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    fun buildTaskQueryByVariables(args: Map<String, Any?>): TaskQuery {
        val tq = createTaskQuery()
        if (args.isNotEmpty()) {
            for ((key, value) in args) {
                if (VariablesEnum.activityName.toString() == key || VariablesEnum.orgName.toString() == key) {
                    tq!!.processVariableValueLike(key, value.toString())
                } else {
                    tq!!.processVariableValueEquals(key, value)
                }
            }
        }
        return tq
    }

    override fun taskCandidateUserByCondition(candidateUser: String, variables: Map<String, Any?>, start: Int, limit: Int): List<Task> {
        return buildTaskQueryByVariables(variables)!!.taskCandidateUser(candidateUser)
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun taskAssigneeByCondition(assignee: String, variables: Map<String, Any?>, start: Int, limit: Int): List<Task> {
        return buildTaskQueryByVariables(variables)!!.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun taskCandidateOrAssignedByCondition(userId: String, variables: Map<String, Any?>, start: Int,
                                                    limit: Int): List<Task> {
        return buildTaskQueryByVariables(variables)!!.taskCandidateOrAssigned(userId).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    override fun countTaskCandidateUser(candidateUser: String): Long {
        return createTaskQuery()!!.taskCandidateUser(candidateUser)
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun countTaskAssignee(assignee: String): Long {
        return createTaskQuery()!!.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun countTaskCandidateOrAssigned(userId: String): Long {
        return createTaskQuery().taskCandidateOrAssigned(userId)
//                .orderByTaskPriority().desc()
//                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun countTaskCandidateUserByCondition(candidateUser: String, variables: Map<String, Any?>): Long {
        return buildTaskQueryByVariables(variables).taskCandidateUser(candidateUser)
//                .orderByTaskPriority().desc()
//                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun countTaskAssigneeByCondition(assignee: String, variables: Map<String, Any?>): Long {
        return buildTaskQueryByVariables(variables).taskAssignee(assignee)
//                .orderByTaskPriority().desc()
//                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun countTaskCandidateOrAssignedByCondition(userId: String, variables: Map<String, Any?>): Long {
        return  buildTaskQueryByVariables(variables).taskCandidateOrAssigned(userId)
//                .orderByTaskPriority().desc()
//                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun processInstanceId(processInstanceId: String): Task? {
        return createTaskQuery()!!.processInstanceId(processInstanceId).active().singleResult()
    }

    override fun findBusinessKeyByTaskId(taskId: String): String? {
        val task = createTaskQuery()!!.taskId(taskId).singleResult()
        val pi = runtimeService.createProcessInstanceQuery().processInstanceId(task.processInstanceId).singleResult()
        return pi?.businessKey
    }

    override fun findVariableByTaskId(taskId: String, variableName: String): String? {
        val value = taskService.getVariable(taskId, variableName)
        return value.toString()
    }

    override fun countTaskAssigneeByTaskQuery(assignee: String, query: TaskQuery): Long {
        return query.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .count()
    }

    override fun taskAssigneeByTaskQuery(assignee: String, query: TaskQuery, start: Int, limit: Int): List<Task> {
        return query.taskAssignee(assignee).orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .listPage(start, limit)
    }

    companion object {
        protected var logger = LoggerFactory.getLogger(TaskQueryHandler::class.java)
    }
}